package com.dk.bleNfc;

import android.Manifest;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import androidx.core.app.ActivityCompat;

import com.dk.bleNfc.BleManager.BleManager;
import com.dk.bleNfc.BleManager.Scanner;
import com.dk.bleNfc.BleManager.ScannerCallback;
import com.dk.bleNfc.DeviceManager.BleNfcDevice;
import com.dk.bleNfc.DeviceManager.ComByteManager;
import com.dk.bleNfc.DeviceManager.DeviceManager;
import com.dk.bleNfc.DeviceManager.DeviceManagerCallback;
import com.dk.bleNfc.Exception.CardNoResponseException;
import com.dk.bleNfc.Exception.DeviceNoResponseException;
import com.dk.bleNfc.Tool.StringTool;
import com.dk.bleNfc.card.Mifare;
import com.gzdh.dishrecognition.config.SysBluetoothConfig;
import com.gzdh.dishrecognition.event.FoodsCard;
import com.gzdh.dishrecognition.event.ScanBlueEvent;

import org.greenrobot.eventbus.EventBus;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by Administrator on 2017/5/2.
 */

public class BleNfcDeviceService extends Service {
    public final static String ACTION_GATT_CONNECTED = "com.dk.bleNfc.BleNfcDeviceService.ACTION_GATT_CONNECTED";
    public final static String ACTION_GATT_DISCONNECTED = "com.dk.bleNfc.BleNfcDeviceService.ACTION_GATT_DISCONNECTED";
    public final static String ACTION_TAG_FIND_TAG = "com.dk.bleNfc.BleNfcDeviceService.ACTION_TAG_FIND_TAG";
    public final static String ACTION_TAG_LOSE_TAG = "com.dk.bleNfc.BleNfcDeviceService.ACTION_TAG_LOSE_TAG";

    public static final String TAG = "BleNfcDeviceService";
    private final IBinder mBinder = new LocalBinder();

    public BleNfcDevice bleNfcDevice;

    public Scanner scanner;
    public ScannerCallback scannerCallback;

    private BluetoothDevice mNearestBle = null;
    private Lock mNearestBleLock = new ReentrantLock();// 锁对象
    private int lastRssi = -100;

    private String writeStr = "";

    private int type = 0;

    public void setType(int type) {
        this.type = type;
    }

    public void setWriteStr(String writeStr) {
        this.writeStr = writeStr;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("服务创建");
        //初始设备操作类
        scanner = new Scanner(BleNfcDeviceService.this, mScannerCallback);
        bleNfcDevice = new BleNfcDevice(BleNfcDeviceService.this);
        bleNfcDevice.setCallBack(mDeviceManagerCallback);

        //开始搜索并连接最近的一个设备
        startScanAndConnectTheNearestDevice();
    }

    //蓝牙搜索回调
    private ScannerCallback mScannerCallback = new ScannerCallback() {
        @Override
        public void onReceiveScanDevice(BluetoothDevice device, int rssi, byte[] scanRecord) {
            super.onReceiveScanDevice(device, rssi, scanRecord);
            if ((scanRecord != null) && (StringTool.byteHexToSting(scanRecord).contains("017f5450"))) {
                if (device.getAddress().equals(SysBluetoothConfig.getInstance().getAddress()) && type == 0) {
                    mNearestBleLock.lock();
                    try {
                        mNearestBle = device;
                        bleNfcDevice.requestConnectBleDevice(mNearestBle.getAddress());
                    } finally {
                        mNearestBleLock.unlock();
                    }
                } else if (type == 1) {
                    EventBus.getDefault().post(new ScanBlueEvent(device.getAddress(), device.getName()));
                }
            }
        }

        @Override
        public void onScanDeviceStopped() {
            if (scannerCallback != null) {
                scannerCallback.onScanDeviceStopped();
            }
            super.onScanDeviceStopped();
        }
    };


    //设备操作类回调
    private DeviceManagerCallback mDeviceManagerCallback = new DeviceManagerCallback() {
        @Override
        public void onReceiveConnectBtDevice(boolean blnIsConnectSuc) {
            super.onReceiveConnectBtDevice(blnIsConnectSuc);
            System.out.println("链接成功 ");
            if (blnIsConnectSuc) {
                Log.d(TAG, "BleNfcDeviceService设备连接成功");
            }

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        boolean isSuc = false;
                        int falseCnt = 0;
                        do {
                            isSuc = bleNfcDevice.startAutoSearchCard((byte) 20, ComByteManager.ISO14443_P4);
                        } while (!isSuc && (falseCnt++ < 10));
                        bleNfcDevice.openBeep(100, 100, 2); //读写卡失败慢响2声
                    } catch (DeviceNoResponseException e) {
                        e.printStackTrace();
                    }
                }
            }).start();


        }

        @Override
        public void onReceiveDisConnectDevice(boolean blnIsDisConnectDevice) {
            super.onReceiveDisConnectDevice(blnIsDisConnectDevice);

            //startScanAndConnectTheNearestDevice();
            Log.d(TAG, "BleNfcDeviceService设备断开链接");
            startScanAndConnectTheNearestDevice();
        }

        @Override
        public void onReceiveConnectionStatus(boolean blnIsConnection) {
            super.onReceiveConnectionStatus(blnIsConnection);
            Log.d(TAG, "BleNfcDeviceService设备链接状态回调");
        }

        @Override
        public void onReceiveInitCiphy(boolean blnIsInitSuc) {
            super.onReceiveInitCiphy(blnIsInitSuc);
        }

        @Override
        public void onReceiveDeviceAuth(byte[] authData) {
            super.onReceiveDeviceAuth(authData);
        }

        @Override
        public void onReceiveRfnSearchCard(boolean blnIsSus, int cardType, byte[] bytCardSn, byte[] bytCarATS) {
            super.onReceiveRfnSearchCard(blnIsSus, cardType, bytCardSn, bytCarATS);
            if (!blnIsSus || cardType == BleNfcDevice.CARD_TYPE_NO_DEFINE) {
                return;
            }
            StringBuilder stringBuffer = new StringBuilder();
            for (byte aBytCardSn : bytCardSn) {
                stringBuffer.append(String.format("%02x", aBytCardSn));
            }

            StringBuilder stringBuffer1 = new StringBuilder();
            for (byte bytCarAT : bytCarATS) {
                stringBuffer1.append(String.format("%02x", bytCarAT));
            }
            Log.d(TAG, "BleNfcDeviceService接收到激活卡片回调：UID->" + stringBuffer + " ATS->" + stringBuffer1);
            try {
                new Thread(() -> {
                    try {
                        bleNfcDevice.stoptAutoSearchCard();
                        int card = getCard();
                        EventBus.getDefault().post(new FoodsCard(card));
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            startAutoSearchCard();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        @Override
        public void onReceiveRfmSentApduCmd(byte[] bytApduRtnData) {
            super.onReceiveRfmSentApduCmd(bytApduRtnData);
            StringBuilder stringBuffer = new StringBuilder();
            for (byte aBytApduRtnData : bytApduRtnData) {
                stringBuffer.append(String.format("%02x", aBytApduRtnData));
            }
            Log.d(TAG, "BleNfcDeviceService接收到APDU回调：" + stringBuffer);
        }

        @Override
        public void onReceiveRfmClose(boolean blnIsCloseSuc) {
            super.onReceiveRfmClose(blnIsCloseSuc);

        }

        @Override
        //按键返回回调
        public void onReceiveButtonEnter(byte keyValue) {
            super.onReceiveButtonEnter(keyValue);
            if (keyValue == DeviceManager.BUTTON_VALUE_SHORT_ENTER) { //按键短按
                Log.d(TAG, "BleNfcDeviceService接收到按键短按回调");
            } else if (keyValue == DeviceManager.BUTTON_VALUE_LONG_ENTER) { //按键长按
                Log.d(TAG, "BleNfcDeviceService接收到按键长按回调");
            }
        }
    };

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //Log.d(TAG, "onStartCommand() executed");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //Log.d(TAG, "onDestroy() executed");
        disconnectBle();
    }

    public class LocalBinder extends Binder {
        public BleNfcDeviceService getService() {
            return BleNfcDeviceService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }


    //直接断开蓝牙的连接，注意：使用此函数不会才生回调
    private void disconnectBle() {
        bleNfcDevice.bleManager.close();
    }

    //开始搜索设备，调用此方法后会一直搜索设备直到调用stopScanDevice方法
    public void startScanDevice() {
        if (!scanner.isScanning()) {
            scanner.startScan(0);
        }
    }

    //开始搜索设备，调用此方法后会一直搜索设备直到调用stopScanDevice方法或者超时
    public void startScanDevice(int delay) {
        if (!scanner.isScanning()) {
            scanner.startScan(delay);
        }
    }

    private boolean startAutoSearchCard() throws DeviceNoResponseException {
        //打开自动寻卡，200ms间隔，寻M1/UL卡
        boolean isSuc = false;
        int falseCnt = 0;
        do {
            isSuc = bleNfcDevice.startAutoSearchCard((byte) 20, ComByteManager.ISO14443_P4);
        } while (!isSuc && (falseCnt++ < 10));
        if (!isSuc) {
            //msgBuffer.delete(0, msgBuffer.length());
        }
        return isSuc;
    }

    //停止搜索设备
    public void stopScanDevice() {
        if (scanner.isScanning()) {
            scanner.stopScan();
        }
    }

    //开始搜索设备并连接最近的一个设备
    public void startScanAndConnectTheNearestDevice() {
        System.out.println("开始搜索设备：状态" + bleNfcDevice.isConnection());
        if ((bleNfcDevice.isConnection() == BleManager.STATE_CONNECTED)) {
            return;
        }
        if (!scanner.isScanning() && (bleNfcDevice.isConnection() == BleManager.STATE_DISCONNECTED)) {
            System.out.println("start");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (this) {
                        System.out.println("搜索启动");
                        scanner.startScan(0);
                        mNearestBleLock.lock();
                        try {
                            mNearestBle = null;
                        } finally {
                            mNearestBleLock.unlock();
                        }
                        lastRssi = -100;

                        while ((mNearestBle == null)
                                && (scanner.isScanning())
                                && (bleNfcDevice.isConnection() == BleManager.STATE_DISCONNECTED)) {
                            try {
                                Thread.sleep(1);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }

                        if (scanner.isScanning() && (bleNfcDevice.isConnection() == BleManager.STATE_DISCONNECTED)) {
                            int searchCnt = 0;
                            while (
                                    (Scanner.deviceList.size() < 2)
                                            && (searchCnt < 1000)
                                            && (scanner.isScanning())
                                            && (bleNfcDevice.isConnection() == BleManager.STATE_DISCONNECTED)) {
                                searchCnt++;
                                try {
                                    Thread.sleep(1);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }

                            scanner.stopScan();
                            mNearestBleLock.lock();
                            try {
                                if (mNearestBle != null) {
                                    scanner.stopScan();
                                    bleNfcDevice.requestConnectBleDevice(mNearestBle.getAddress());
                                }
                            } finally {
                                mNearestBleLock.unlock();
                            }
                        } else {
                            scanner.stopScan();
                        }
                    }
                }
            }).start();
        }
    }

    private boolean write(int val) throws Exception {
        final Mifare mifare = (Mifare) bleNfcDevice.getCard();
        byte[] key = {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
        try {
            boolean anth = mifare.authenticate((byte) 4, Mifare.MIFARE_KEY_TYPE_A, key);
            if (anth) {
                byte[] bytes = new byte[8];
                bytes[0] = (byte) ((val & 0x000000FF) >> 0);
                bytes[1] = (byte) ((val & 0x0000FF00) >> 8);
                bytes[2] = (byte) ((val & 0x00FF0000) >> 16);
                bytes[3] = (byte) ((val & 0xFF000000) >> 24);
                boolean isSuc = mifare.write((byte) 4, new byte[]{bytes[0], bytes[1], bytes[2], bytes[3], 0x00, 0x00, 0x00, 0x00, (byte) 0x00,
                        (byte) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
                if (!isSuc) {
                    return false;
                }
                bleNfcDevice.openBeep(100, 100, 10);
                return true;
            } else {
                System.out.println("密码校验失败");
                return false;
            }
        } catch (CardNoResponseException e) {
            e.printStackTrace();
            return false;
        }
    }

    private int getCard() throws Exception {
        int card = 0;
        final Mifare mifare = (Mifare) bleNfcDevice.getCard();
        byte[] key = {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
        boolean anth = mifare.authenticate((byte) 4, Mifare.MIFARE_KEY_TYPE_A, key);
        if (anth) {
            byte[] readDataBytes = mifare.read((byte) 4);
            card = bytes2Int32(readDataBytes);
            bleNfcDevice.openBeep(200, 100, 1);
        }
        return card;
    }


    public static long bytes2Int64(byte[] bytes) {
        long hval = (((long) (bytes[7] & 0xFF) << 56) | ((long) (bytes[6] & 0xFF) << 48) | ((long) (bytes[5] & 0xFF) << 40) | ((long) (bytes[4] & 0xFF) << 32)
                | ((long) (bytes[3] & 0xFF) << 24) | ((long) (bytes[2] & 0xFF) << 16) | ((long) (bytes[1] & 0xFF) << 8) | ((long) (bytes[0] & 0xFF) << 0));
        return hval;
    }

    public static int bytes2Int32(byte[] bytes) {
        return (((bytes[3] & 0xFF) << 24) | ((bytes[2] & 0xFF) << 16) | ((bytes[1] & 0xFF) << 8) | ((bytes[0] & 0xFF) << 0));
    }

    public void startScan() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (this) {
                    scanner.startScan(0);
                    for (int i = 0; i < 30; i++) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    type = 0;
                    scanner.stopScan();
                }
            }
        }).start();

    }

    public void reConnect() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                bleNfcDevice.requestDisConnectDevice();
//                disconnectBle();

                type = 0;
//                startScanAndConnectTheNearestDevice();
            }
        }).start();
    }
}
